package com.bright.hxj.cwduijie.service.impl;

import cn.hutool.core.net.URLDecoder;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.bright.ghj.common.config.BizThreadPoolExt;
import com.bright.ghj.common.util.DateUtil;
import com.bright.ghj.common.util.StringUtil;
import com.bright.hxj.cwduijie.constant.SystemConstants;
import com.bright.hxj.cwduijie.enums.DataApi;
import com.bright.hxj.cwduijie.enums.SJJHBZ;
import com.bright.hxj.cwduijie.manager.DataManager;
import com.bright.hxj.cwduijie.manager.DuijieManager;
import com.bright.hxj.cwduijie.pojo.bo.ApiDataCollection;
import com.bright.hxj.cwduijie.pojo.bo.ProcInfo;
import com.bright.hxj.cwduijie.pojo.command.*;
import com.bright.hxj.cwduijie.pojo.dto.*;
import com.bright.hxj.cwduijie.pojo.po.*;
import com.bright.hxj.cwduijie.pojo.query.BatchQuery;
import com.bright.hxj.cwduijie.pojo.query.DuijieQuery;
import com.bright.hxj.cwduijie.pojo.query.PageQuery;
import com.bright.hxj.cwduijie.service.*;
import com.bright.hxj.cwduijie.util.CommonUtil;
import com.bright.hxj.cwduijie.util.EntityManagerUtil;
import com.bright.ghj.common.util.ListUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.EntityManager;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @Author hxj
 * @Date 2024/7/4 15:31
 * @Description
 */

@Component
@RequiredArgsConstructor
@Slf4j
public class DuijieServiceImpl implements DuijieService {

    private final BizThreadPoolExt bizPool;
    private final BizThreadPoolExt jobPool;

    private final BizThreadPoolExt fileUploadPool;

    private final HttpClient httpClient;

    private final DataManager dataManager;

    private final EntityManager entityManager;

    private final ObjectMapper objectMapper;

    private final DuijieManager duijieManager;

    private final DataBusiness dataBusiness;

//    @Qualifier("normal")
//    private final WebExchangeService webExchangeService;

    private final CheckServiceImpl checkService;

//    private final ConfigConstants constants;

    private final ApiServiceFactory factory;

    public void duijie() throws JsonProcessingException {
        duijie(new DuijieCommand());
    }

    /**
     * 对接主方法（旧 将接口分成N个批次一批批对接的版本）
     */
    public void duijie(DuijieCommand duijieCommand) throws JsonProcessingException {

        // 获取各个接口需要对接的账套
        List<AbstractApiService<?>> needDuijieApis = factory.getNeedDuijieApis(duijieCommand);

        List<String> needDuijieZtDataKeys = dataBusiness.getNeedDuijieAccSetsByDuijieCommand(duijieCommand, needDuijieApis);

        DuijieQuery dq = new DuijieQuery();
        dq.setZtDataKeys(needDuijieZtDataKeys);
        List<AccSet> needDuijieAccSets = dataManager.getAccSetsByDataKeys(dq);

        checkService.doCheckBeforeStart(duijieCommand, needDuijieAccSets, needDuijieApis);

        ApiAccSetServiceImpl accSetService = factory.getAccSetService();
        if (needDuijieApis.contains(accSetService)) {
            accSetService.sendAccSetDelete(needDuijieZtDataKeys);
        }

        List<AccSet> accSetsAfterFilter = dataBusiness.getAccSetsAfterFilter(duijieCommand, needDuijieAccSets);

        log.info("需要推送的账套数量：" + accSetsAfterFilter.size());

        // 先推送第零批 把账套一千条推一次 20240722 撤销 否则一个失败全部失败
//        sendAccSetDataPerThousand(needDuijieZtDataKeys);

        // 循环各个账套 按账套顺序对接
        for (AccSet needDuijieAccSet : accSetsAfterFilter) {
            String needDuijieZtDataKey = needDuijieAccSet.getDATA_KEY();
            // 20240719 改成每个账套一个线程来推送
            CompletableFuture.runAsync(() -> {
                        Thread.currentThread().setName(needDuijieZtDataKey + "_async");
                        log.debug("线程启动 " + needDuijieZtDataKey);
                        try {
                            dataBusiness.duijieByAccSet(duijieCommand, needDuijieZtDataKey);
                        } catch (JsonProcessingException e) {
                            throw new RuntimeException(e);
                        }
                    }, bizPool)
                    .exceptionally(throwable -> {
                        throwable.printStackTrace();
                        log.error("duijie 线程执行异常：", throwable);
                        return null;
                    });



        }
        log.debug("本次对接调用完成，等待返回结果");
    }



    @Override
    @Transactional
    public void build(BuildCommand buildCommand) {
        List<Object> accSets = dataBusiness.getAccSetsListByBuildCommand(buildCommand);
//        buildByAccSets(buildCommand, accSets);
        log.info("开始调用存储过程生成账套数据，共" + accSets.size() + "个账套");
        int count = 0;
        for (Object accSet : accSets) {
            count ++;
            log.info("生成账套数据中，进度：" + count + "/" + accSets.size() + ", 当前账套号：" + accSet);
            dataManager.executeSPT(accSet, buildCommand);
        }

    }


    @Override
    public void buildOneAndStartOne(BuildCommand buildCommand, DuijieCommand duijieCommand) throws JsonProcessingException {
        // 修改顺序 生成一套 对接一套

        List<Object> accSets = dataBusiness.getAccSetsListByBuildCommand(buildCommand);
//        List<String> needDuijieAccSetsByDuijieCommand = getNeedDuijieAccSetsByDuijieCommand(duijieCommand);
        int count = 0;
        log.info("开始调用存储过程生成账套数据，共" + accSets.size() + "个账套");
        for (Object accSet : accSets) {
            count ++;
            // 生成一套
            List<Object> singleAccSet = Collections.singletonList(accSet);
//            buildByAccSets(buildCommand, singleAccSet);

            log.info("生成账套数据中，进度：" + count + "/" + accSets.size() + ", 当前账套号：" + accSet);
            dataManager.executeSPT(accSet, buildCommand);

            List<String> ztDataKey = dataManager.getZtDataKeyByAccSets(singleAccSet);

            if (ztDataKey.size() > 0) {
                // 对接一套
                dataBusiness.duijieByAccSet(duijieCommand, ztDataKey.get(0));
            }

        }

    }


    /**
     * 查异步任务的
     */
    @Override
    public void checkAsyncTasks() {

        List<DuijieAsyncDto> duijieAsyncDtos = duijieManager.getNeedCheckAsyncTasksData();
        if (duijieAsyncDtos.size() == 0) {
            return;
        }

        // 获取需要查询任务状态的数据
        List<String> taskIds = ListUtil.toSingleList(duijieAsyncDtos, DuijieAsyncDto::getTaskId);
        // 一千条执行一次
        int count = 0;
        int countPerTime = 100;
        while (count < taskIds.size()) {

            List<String> subTaskIds = ListUtil.getSubList(taskIds, count, count+countPerTime);
            int finalCount = count;

            CompletableFuture.runAsync(() -> {
                        Thread.currentThread().setName(finalCount + "_checkAsyncTasks");
                        log.debug(finalCount + "_checkAsyncTasks线程启动");
                        dataBusiness.queryTaskIdResultByThread(duijieAsyncDtos, taskIds, subTaskIds);
                        log.debug("获取taskId进度：" + finalCount + "/" + taskIds.size());
                    }, jobPool)
                    .exceptionally(throwable -> {
                        throwable.printStackTrace();
                        log.error("checkAsyncTasks 线程执行异常：", throwable);
                        return null;
                    });

            count += countPerTime;
        }
    }

    @Override
    public void startNextBatch() {

        List<DuijieBatchDto> batches = duijieManager.getNeedDuijieBatches();

        for (DuijieBatchDto batch : batches) {
            // 对接该批次数据
            // 也改成一个批次一个线程执行
            CompletableFuture.runAsync(() -> {
                        Thread.currentThread().setName(batch.getBatchId() + "_batch");
                        log.debug("线程启动 " + batch.getBatchId());
                        try {
                            dataBusiness.startByZtDataKeyAndBatchOrder(batch);
                        } catch (JsonProcessingException e) {
                            throw new RuntimeException(e);
                        }

                    }, bizPool)
                    .exceptionally(throwable -> {
                        throwable.printStackTrace();
                        log.error("duijie 线程执行异常：", throwable);
                        return null;
                    });


        }
    }


    /**
     * 20240721 遂溪、麻章特殊 只推一批
     * 对接主方法
     * @param duijieCommand
     * @return
     * @throws JsonProcessingException
     */
    @Override
    public String startByOnlyOneBatch(DuijieCommand duijieCommand) throws JsonProcessingException {

        // 获取所有需要对接的接口
        List<AbstractApiService<?>> needDuijieApis = factory.getNeedDuijieApis(duijieCommand);

        // 获取各个接口需要对接的账套
        List<String> needDuijieZtDataKeys = dataBusiness.getNeedDuijieAccSetsByDuijieCommand(duijieCommand, needDuijieApis);

        DuijieQuery dq = new DuijieQuery();
        dq.setZtDataKeys(needDuijieZtDataKeys);
        List<AccSet> needDuijieAccSets = dataManager.getAccSetsByDataKeys(dq);

        checkService.doCheckBeforeStart(duijieCommand, needDuijieAccSets, needDuijieApis);

        // 20240807 先推送所有需要删除的账套数据
        ApiAccSetServiceImpl accSetService = factory.getAccSetService();
        if (needDuijieApis.contains(accSetService)) {
            accSetService.sendAccSetDelete(needDuijieZtDataKeys);
        }

        // v.1.5.12 过滤后的账套
        List<AccSet> needDuijieAccSetsAfterFilter = dataBusiness.getAccSetsAfterFilter(duijieCommand, needDuijieAccSets);

        // 循环各个账套 按账套顺序对接
        int total = needDuijieAccSetsAfterFilter.size();
        AtomicInteger sharedCounter = new AtomicInteger(1);
        for (AccSet accSet : needDuijieAccSetsAfterFilter) {
            String needDuijieZtDataKey = accSet.getDATA_KEY();

            // 20240719 改成每个账套一个线程来推送
            CompletableFuture.runAsync(() -> {
                        Thread.currentThread().setName(needDuijieZtDataKey + "_async");
                        log.debug("线程启动 " + needDuijieZtDataKey);
                        try {
                            dataBusiness.duijieByAccSetOneBatchNew(duijieCommand, accSet, needDuijieZtDataKey, needDuijieApis, false);

                            // v1.6.5 获取至今为止执行完成的线程数量
                            int finishCountTillNow = sharedCounter.getAndIncrement();

                            log.info("按账套对接 进度：" + finishCountTillNow + "/" + total + " 当前账套：" + accSet.getMC());
                            if (finishCountTillNow == total) {
                                log.info("全部账套对接结束！");
                            }
                        } catch (JsonProcessingException e) {
                            throw new RuntimeException(e);
                        }
                    }, bizPool)
                    .exceptionally(throwable -> {
                        throwable.printStackTrace();
                        int finishCountTillNow = sharedCounter.getAndIncrement();
                        log.error("duijie 进度：" + finishCountTillNow + " 线程执行异常：", throwable);
                        return null;
                    });

        }
        String message = "对接已开始，本次需要推送的账套数量：" + needDuijieAccSets.size() + ", 筛选后账套数量：" + needDuijieAccSetsAfterFilter.size();
        log.info(message);

        return message;

    }



    @Override
    public void checkBatchIfAllEnd() {
        // 检查是否有批次已经全部结束了

        // 查询还未执行完的批次
        List<DuijieBatchDto> batches = duijieManager.getExecutingBatches();

        for (DuijieBatchDto batch : batches) {
            // 检查这些批次的所有数据是否全部执行完毕（如果存在3的就是3 不更新 全部1是1 剩下都是2（代表存在失败数据 只要有一条失败数据都不往下继续走））

            List<DuijieAsyncDto> duijieAsyncDtos = duijieManager.getCheckAsyncTasksByBatchId(new BatchQuery(batch.getBatchId()));
            List<Integer> sjjhbzList = ListUtil.toSingleList(duijieAsyncDtos, DuijieAsyncDto::getSjjhbz);
            SJJHBZ saveSjjhbz = SJJHBZ.SUCCESS;
            if (sjjhbzList.contains(SJJHBZ.ERROR.getValue())) {
                saveSjjhbz = SJJHBZ.ERROR;
            }
            if (sjjhbzList.contains(SJJHBZ.EXECUTING.getValue()) || sjjhbzList.contains(SJJHBZ.FEEDBACK_BUT_NOT_CHECK_COMPLETE.getValue())) {
                // 存在还没返回结果的 继续等待
                continue;
            }

            if (sjjhbzList.size() == 0) {
                // 没有数据 就是还没轮到这个批次执行 跳过
                // 20240717 但如果超过1天还一直没有对应数据 就是异常
                if (DateUtil.getDaysBetween(new Date(), batch.getCreateDate()) > 1) {
                    saveSjjhbz = SJJHBZ.ERROR;
                } else {
                    continue;
                }
            } else {
                for (Integer sjjhbz : sjjhbzList) {
                    if (sjjhbz != SJJHBZ.SUCCESS.getValue() /*&& sjjhbz != SJJHBZ.FEEDBACK_BUT_NOT_CHECK_COMPLETE.getValue()*/) {
                        // 存在异常的数据 则整批数据都算异常
                        saveSjjhbz = SJJHBZ.ERROR;
                        break;
                    }
                }
            }

            // 保存sjjhbz
            batch.setSjjhbz(saveSjjhbz.getValue());
            batch.setWriteDate(new Date());
            if (saveSjjhbz.getValue() == SJJHBZ.SUCCESS.getValue()) {
                batch.setWriteLog("本批次完成，" + (sjjhbzList.size() == 0 ? "无接口需推送" : "对接成功！"));
                // 更新下一个批次的sjjhbz为0 （需要对接）
                duijieManager.updateNextBatchDataToDuijie(batch.getNextBatchId());
            } else {
                List<DuijieAsyncDto> errorDuijieAsyncs = ListUtil.toListByFilter(duijieAsyncDtos, duijieAsyncDto -> duijieAsyncDto.getSjjhbz() != SJJHBZ.SUCCESS.getValue());
                List<String> errorTaskIds = ListUtil.toSingleList(errorDuijieAsyncs, DuijieAsyncDto::getTaskId);
                batch.setWriteLog(errorTaskIds.size() > 0 ? ("该批次存在异常数据：" + errorTaskIds) : "不存在对应批次数据");
            }
        }
        duijieManager.saveBatchData(batches);

    }

    @Override
    public void test(Integer accSet) {
//        AccSet accSet1 = dataManager.getAccSet(accSet);
//        System.out.println(accSet1.getMc());

    }

    @Override
    public String[] getNeedDuijieAccSetsExceptExecuting() {

        // 通过对接批次表获取还有数据在等待中的账套
        List<DuijieBatchDto> executingBatches = duijieManager.getExecutingBatches();
        Set<String> ztDataKeys = new HashSet<>();
        ztDataKeys.addAll(ListUtil.toSingleList(executingBatches, DuijieBatchDto::getZtDataKey));
        // 根据ztDataKey获取统一信用代码 再通过acc_set表获取账套号
        DuijieQuery duijieQuery = new DuijieQuery();
        duijieQuery.setZtDataKeys(new ArrayList<>(ztDataKeys));
        List<AccSet> accSetsByDataKeys = dataManager.getAccSetsByDataKeys(duijieQuery);
        List<String> creditCodes = ListUtil.toSingleList(accSetsByDataKeys, AccSet::getTYSHXYDM);

        Map<String, Object> params = new HashMap<>();
        params.put("creditCode", creditCodes);

        List<Map<String, Object>> maps = EntityManagerUtil.queryForMapList(entityManager,
                "select acc_set as ACC_SET from " + dataManager.getCwDBName() + "acc_set where isnull(zucode,'') not in (:creditCode)", params);
        List<Object> acc_sets = ListUtil.toSingleList(maps, map -> map.get("ACC_SET"));
        String[] result = new String[acc_sets.size()];
        int i = 0;
        for (Object acc_set : acc_sets) {
            result[i] = acc_set.toString();
            i++;
        }


        return result;
    }

    @Override
    public void deleteDataKeys(String serviceCode) throws JsonProcessingException {
        String writeServiceCode = StringUtil.replace(serviceCode, "D", "W");
//        List<AbstractApiService<?>> apis = factory.getApisByServiceCode(Collections.singletonList(writeServiceCode));
//        if (apis.size() == 0) return;

        List<String> dataKeysAlreadyDeleted = duijieManager.getDataKeysAlreadyDeleted(writeServiceCode);

        Optional<DataApi> optionalDataApi = DataApi.ofOptional(serviceCode);
        DataApi deleteApi = optionalDataApi.orElseThrow(() -> new RuntimeException("serviceCode异常：" + serviceCode));

        dataBusiness.sendNeedDeleteData(null, dataKeysAlreadyDeleted, deleteApi, dataKeys -> dataKeys, dataKeys -> 0, null);
    }


    @Override
    public void syncTaskResultToDataTables() {
        List<AbstractApiService<?>> needDuijieApis = factory.getAllDuijieApis();
        for (AbstractApiService<?> needDuijieApi : needDuijieApis) {
            DataApi dataApi = needDuijieApi.getDataApi();
            String tableName = dataApi.getTableName();
            // 查询是否有需要更改状态的数据
            Long count = duijieManager.getNeedSendDataResultStatusCount(tableName);
            if (count > 0) {

                // 有 则同步sjjhbz的值
                SaveSendDataResultCommand command = new SaveSendDataResultCommand();
                command.setDataApi(dataApi);
                duijieManager.updateSendDataResultStatus(command);

            }
        }


    }



    /**
     * 对接附件
     */
    @Override
    public void sendFiles(DuijieQuery duijieQuery, String batchId) {

        //先删除附件
//        deleteFiles(duijieQuery, batchId);

        //查询需要对接的附件
        List<DjFile> needDuiJieFiles = dataManager.getNeedDuiJieFiles(duijieQuery);

        //循环附件信息
        for (DjFile needDuiJieFile : needDuiJieFiles) {

            //异步进行数据推送
//            asyncSendFile(needDuiJieFile);
            CompletableFuture.runAsync(() -> {
                Thread.currentThread().setName(needDuiJieFile.getID() + "_" + needDuiJieFile.getDATA_KEY() + "_" + needDuiJieFile.getFILENAME());
                asyncSendFile(needDuiJieFile);
            }, fileUploadPool).exceptionally(throwable -> {
                throwable.printStackTrace();
                log.error("sendFiles 线程执行异常：", throwable);
                return null;
            });

        }
    }


    /**
     * 异步发送附件
     * @param djFile 附件内容
     */
    public void asyncSendFile(DjFile djFile) {

        StringBuilder url = new StringBuilder("");

        SendFileDto sendFileDto = new SendFileDto();
        sendFileDto.setBusinessDataKey(djFile.getBUSINESS_DATA_KEY());
        sendFileDto.setTyshxydm(djFile.getTYSHXYDM());
        sendFileDto.setDataKey(djFile.getDATA_KEY());
        sendFileDto.setFileDateTime(LocalDateTime.now());

        //下载路径
        String name = djFile.getNAME();

        //原始文件
        String oldFileName = djFile.getFILENAME();

        url.setLength(0);
        url.append(djFile.getDOMAIN());
        url.append(name);



        HttpGet requestGet = new HttpGet(url.toString());
        HttpResponse responseResult = null;
        try {
            responseResult = httpClient.execute(requestGet);
        } catch (IOException e) {

            DataApi dataApi = Objects.requireNonNull(DataApi.of(djFile.getADD_UPLOAD_FILE_METHOD()));


            // 存到各张数据表的sjjhbz
            SaveSendDataResultCommand command = new SaveSendDataResultCommand();
            command.setDataApi(dataApi);
            command.setSjjhbz(SJJHBZ.ERROR.getValue());
            command.setTaskId(null);
            command.setIds(Collections.singletonList(djFile.getID()));
            duijieManager.saveSendDataResult(command);

            SaveTaskIdCommand saveTaskIdCommand = new SaveTaskIdCommand();
            saveTaskIdCommand.setTaskId(null);
            saveTaskIdCommand.setServiceCode(djFile.getADD_UPLOAD_FILE_CODE());
            saveTaskIdCommand.setType(dataApi.getDescription() + "-" + dataApi.getTableName());
            saveTaskIdCommand.setErrorMsg(e.getMessage());
            saveTaskIdCommand.setSjjhbz(SJJHBZ.ERROR.getValue());
            saveTaskIdCommand.setContent(djFile.getDOMAIN() + djFile.getNAME());
            duijieManager.saveAsyncTaskId(saveTaskIdCommand);
            log.error("网络请求异常： url: [{}]", url);
            return;
        }

        assert responseResult != null;
        //请求文件成功
        if (responseResult.getStatusLine().getStatusCode() == 200) {

            log.debug("文件下载成功 url: [{}]: ", url);

            try(ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {

                //保存下载的文件
                responseResult.getEntity().writeTo(byteArrayOutputStream);
                byte[] bytes = byteArrayOutputStream.toByteArray();

                sendFileDto.setFile(bytes);
                sendFileDto.setFileName(oldFileName);
                byteArrayOutputStream.close();
                dataBusiness.sendFile(sendFileDto, DataApi.of(djFile.getADD_UPLOAD_FILE_CODE()), Collections.singletonList(djFile.getID()));
//                //异步进行数据推送
//                CompletableFuture.runAsync(() -> {
//                    Thread.currentThread().setName(djFile.getID() + "_" + djFile.getDATA_KEY() + "_" + djFile.getFILENAME());
//
//                }, fileUploadPool).exceptionally(throwable -> {
//                    throwable.printStackTrace();
//                    log.error("sendFiles 线程执行异常：", throwable);
//                    return null;
//                });

            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            try {
                log.error("下载文件失败 url : [{}] 错误信息: [{}]", url, EntityUtils.toString(responseResult.getEntity()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 删除附件
     */
    @Override
    public void deleteFiles(DuijieQuery duijieQuery, String batchId)  {

        //查询需要删除的附件
//        DuijieQuery duijieQuery = new DuijieQuery();
//        duijieQuery.setOpType(OpType.DEL);
//        duijieQuery.setCreditCode("N2440111C14911208Y");

        List<DjFile> needDuiJieFiles = dataManager.getNeedDuiJieFiles(duijieQuery);

        Map<String, List<String>> methodFileList = new HashMap<>();
        Map<String, List<Integer>> methodIdList = new HashMap<>();

        for (DjFile needDuiJieFile : needDuiJieFiles) {

            String deleteUploadFileCode = needDuiJieFile.getDELETE_UPLOAD_FILE_CODE();

            //保存不同操作类型的所有附件的data_key
            List<String> dataKeys = methodFileList.getOrDefault(deleteUploadFileCode, new ArrayList<>(1));
            dataKeys.add(needDuiJieFile.getDATA_KEY());
            methodFileList.put(deleteUploadFileCode, dataKeys);


            //保存不同操作类型的所有附件的id
            List<Integer> ids = methodIdList.getOrDefault(deleteUploadFileCode, new ArrayList<>(1));
            ids.add(needDuiJieFile.getID());
            methodIdList.put(deleteUploadFileCode, ids);
        }

        //循环删除
        Map<String, Object> deleteMap = new HashMap<>();
        for (String temp : methodFileList.keySet()) {
            deleteMap.put("DATA_KEYS", methodFileList.get(temp));
            try {
                dataBusiness.sendMapData(deleteMap, DataApi.of(temp), methodIdList.get(temp), batchId, null);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public void sendVoucherWithDefaultVoucherEntry(List<SendDefaultVoucherEntryCommand> commands) throws JsonProcessingException {
//        ApiVoucherServiceImpl voucherService = factory.getVoucherService();

        for (SendDefaultVoucherEntryCommand command : commands) {
            // 获取推送报文
            String ztDataKey = command.getZtDataKey();
            String kjqj = command.getKjqj();

            YearMonth yearMonth = CommonUtil.getYearMonthFromKJQJString(kjqj);
//            DuijieCommand duijieCommand = new DuijieCommand(yearMonth.getYear(), yearMonth.getMonthValue(), null);
            DuijieQuery duijieQuery = new DuijieQuery();
            duijieQuery.setZtDataKey(ztDataKey);
            duijieQuery.setDuijieYears(yearMonth.getYear());
            duijieQuery.setDuijieMonths(yearMonth.getMonthValue());
            ApiFlushVoucherServiceImpl flushVoucherService = factory.getFlushVoucherService();
            ApiDataCollection apiDataCollection = new ApiDataCollection();
            flushVoucherService.getData(apiDataCollection, duijieQuery);
            flushVoucherService.sendData(apiDataCollection, duijieQuery, null);

//            // 通过DUIJIE_DATA_KEYS表获取推过的dataKey
//            String dataKeyPrefix = ztDataKey + "-" + kjqj;
//            List<DuijieDataKeysDto> duijieDataKeysDtos = duijieManager.getDuijieDataKeysLike(DataApi.VOUCHER.getServiceCode(), dataKeyPrefix);
//            if (duijieDataKeysDtos.size() == 0) {
//                throw new RuntimeException("DUIJIE_DATA_KEY找不到历史推送凭证记录！");
//            }
//
//            List<String> historyDataKeys = duijieDataKeysDtos.stream().map(DuijieDataKeysDto::getDataKey)
//                    .distinct().collect(Collectors.toList());
//            pushDefaultVoucherEntryByDataKeys(voucherService, ztDataKey, kjqj, historyDataKeys);
        }

    }

    private void pushDefaultVoucherEntryByDataKeys(String ztDataKey, String kjqj, List<String> dataKeys) throws JsonProcessingException {
//        String template = "{  \"DATA_KEY\": \"${DATA_KEY}\",  \"ZT_DATA_KEY\": \"${ZT_DATA_KEY}\",  \"BCXPZ_DATA_KEY\": \"\",  \"KJQJ\": \"${KJQJ}\",  \"LY\": 2,  \"LY_REMARK\": \"\",  \"ZDR\": \"-                      \",  \"PZRQ\": \"2024-03-31\",  \"FJS\": 0,  \"SHR\": \"-                          \",  \"ZT\": 50,  \"LX\": 10,  \"PZXH\": ${XH},  \"JZR\": \"-                      \",  \"THYY\": \"\",  \"KJPZ_KJKM_LIST\": [{   \"DATA_KEY\": \"${DATA_KEY}\",   \"ZT_DATA_KEY\": \"${ZT_DATA_KEY}\",   \"DF_JE\": \"\",   \"ZY\": \"提现金\",   \"KJKM_BM\": \"101\",   \"JF_JE\": \"8700.00\"  }, {   \"DATA_KEY\": \"${DATA_KEY}\",   \"ZT_DATA_KEY\": \"${ZT_DATA_KEY}\",   \"DF_JE\": \"8700.00\",   \"ZY\": \"提现金\",   \"KJKM_BM\": \"401\",   \"JF_JE\": \"\"  }] }";
//        List<Map<String, Object>> contents = new ArrayList<>();
//        for (String historyDataKey : dataKeys) {
//            String content = StringUtil.replace(template, "${DATA_KEY}", historyDataKey);
//            String xh = StringUtil.substringAfterLast(historyDataKey, "-");
//            content = StringUtil.replace(content, "${ZT_DATA_KEY}", ztDataKey);
//            content = StringUtil.replace(content, "${KJQJ}", kjqj);
//            content = StringUtil.replace(content, "${XH}", xh);
//
//            Map map = objectMapper.readValue(content, Map.class);
//            contents.add(map);
//        }
//
//        voucherService.sendObjectData(contents, DataApi.VOUCHER, Collections.emptyList(), ztDataKey, null);

        ApiFlushVoucherServiceImpl flushVoucherService = factory.getFlushVoucherService();
        flushVoucherService.pushDefaultVoucherEntry(ztDataKey, kjqj, dataKeys);
    }


    // 指定更新哪些id的数据交换标志
    @Override
    public void updateSjjhbzByServiceCodeAndIds(UpdateOpTypeSjjhbzCommand command, DataApi dataApi) {
        duijieManager.updateOpTypeAndSjjhbzByIds(command, dataApi);
    }

    // v1.6.7 处理凭证报错 账套[44-xx]当前启用的会计期间是[2024年1月]，参数中传入的凭证会计期间是[2024年2月]：一个账套下的凭证必须属于同一个当前启用或已月结的会计期间
    @Override
    public void processVoucherError(ProcessVoucherErrorCommand command) throws JsonProcessingException {
        String finallyYjKjqj = command.getFinallyYjKjqj();
        YearMonth finallyYjYearMonth = CommonUtil.getYearMonthFromKJQJString(finallyYjKjqj);

        // 查询所有属于这种类型的报错
        String sql = "select ZT_DATA_KEY,KJQJ,a.taskId as taskId,methodNo as methodNo,type as \"type\",sjjhbz as sjjhbz,writeLog as writeLog," +
                "createDate as createDate,writeDate as writeDate,batchId as batchId,acc_set as acc_set from (\n" +
                "select ZT_DATA_KEY,KJQJ,taskId from DJ_PZM where sjjhbz=2 group by ZT_DATA_KEY,KJQJ,taskId\n" +
                ") a, DUIJIE_ASYNC b where a.taskId=b.taskId and writeLog like '%当前启用的会计期间是%参数中传入的凭证会计期间是%一个账套下的凭证必须属于同一个当前启用或已月结的会计期间%'" +
                " order by ZT_DATA_KEY,KJQJ";
        List<Map<String, Object>> maps = EntityManagerUtil.queryForMapList(entityManager, sql, Collections.emptyMap());

        // 按账套分类
        Map<String, List<Map<String, Object>>> groupByZtMap = new HashMap<>();
        for (Map<String, Object> map : maps) {
            String ztDataKey = (String) map.get("ZT_DATA_KEY");
            groupByZtMap.putIfAbsent(ztDataKey, new ArrayList<>());
            groupByZtMap.get(ztDataKey).add(map);
        }

        for (Map.Entry<String, List<Map<String, Object>>> entry : groupByZtMap.entrySet()) {
            String ztDataKey = entry.getKey();
            YearMonth beginYjYearMonth, endYjYearMonth = null;
            // 是否这个账套的第一条数据
            boolean isFirstDataOfZt = true;
            List<DuijieBatchDto> duijieBatchDtos = new ArrayList<>();

            for (Map<String, Object> map : entry.getValue()) {
                try {
                    // 对于每一个账套 按月份顺序梳理报错
                    if (endYjYearMonth != null) {
                        // 查lastYjMap看是否有推过哪个月份的月结 如果有 则用这个月份的下一个月
                        beginYjYearMonth = endYjYearMonth.plusMonths(1);
                    } else {
                        // 还没推过这个账套
                        // 识别出当前启用的会计期间
                        String writeLog = (String) map.get("writeLog");
                        beginYjYearMonth = CommonUtil.getEnableYearMonth(writeLog);
                    }

                    // 获取报错的凭证是推的哪个月的凭证 月结推到上一个月
                    String kjqj = (String) map.get("KJQJ");
                    YearMonth voucherYearMonth = CommonUtil.getYearMonthFromKJQJString(kjqj);
                    endYjYearMonth = voucherYearMonth.plusMonths(-1);

                    // 月结和凭证的批次id
//                    String yjBatchbatchId = ztDataKey + "-" + System.currentTimeMillis() + "-yjBatch";
                    String voucherBatchId = ztDataKey + "-" + System.currentTimeMillis() + "-pz";

                    // 从上面得出的月份区间开始推月结 推到当前凭证会计期间的上一个月 插入批次数据
                    List<YearMonth> yearMonthsBetween = DateUtil.getYearMonthsBetween(LocalDate.of(beginYjYearMonth.getYear(), beginYjYearMonth.getMonthValue(), 1), LocalDate.of(endYjYearMonth.getYear(), endYjYearMonth.getMonthValue(), 1));
                    if (yearMonthsBetween.size() > 0) {
                        addYjBatchesByYearMonthsBetween(ztDataKey, duijieBatchDtos, voucherBatchId, yearMonthsBetween);

                        if (isFirstDataOfZt) {
                            DuijieBatchDto firstBatch = duijieBatchDtos.get(0);
                            if (command.isTest()) {
                                firstBatch.setSjjhbz(SJJHBZ.EXECUTING.getValue());
                            } else {
                                firstBatch.setSjjhbz(SJJHBZ.WAITING.getValue());
                            }
                        }
                    }

                    // 插入批次数据 凭证批次
                    DuijieBatchDto voucherBatchDto = new DuijieBatchDto(null, ztDataKey, voucherBatchId, 2, new Date());
                    voucherBatchDto.setYears(voucherYearMonth.getYear());
                    voucherBatchDto.setMonths(voucherYearMonth.getMonthValue());
//                    if (isFirstDataOfZt && yearMonthsBetween.size() == 0) {
//                        // 如果本轮不用等推送月结 则直接开始 （不存在这种情况 要么第一轮肯定要推月结 要么第二三四轮都还没轮到凭证 ）
//                        voucherBatchDto.setSjjhbz(SJJHBZ.WAITING.getValue());
//                    }
                    duijieBatchDtos.add(voucherBatchDto);

                    isFirstDataOfZt = false;
                } catch (Throwable throwable) {
                    log.error("", throwable);
                }
            }
            // 补充推月结 推到目标月份
            if (finallyYjYearMonth != null && endYjYearMonth != null) {
                // 获取推的凭证的年月 是最后一次推月结的下一个月
                endYjYearMonth = endYjYearMonth.plusMonths(1);
                // 从上面得出的月份区间开始推月结 推到当前凭证会计期间的上一个月 插入批次数据
                List<YearMonth> yearMonthsBetween = DateUtil.getYearMonthsBetween(LocalDate.of(endYjYearMonth.getYear(), endYjYearMonth.getMonthValue(), 1), LocalDate.of(finallyYjYearMonth.getYear(), finallyYjYearMonth.getMonthValue(), 1));
                if (yearMonthsBetween.size() > 0) {
                    addYjBatchesByYearMonthsBetween(ztDataKey, duijieBatchDtos, null, yearMonthsBetween);
                }
            }

            duijieManager.saveBatchData(duijieBatchDtos);
        }
        log.info("凭证错误已扫描完成，等待批次推送");
    }

    // 生成指定年月区间的月结批次数据
    private void addYjBatchesByYearMonthsBetween(String ztDataKey, List<DuijieBatchDto> duijieBatchDtos, String lastBatchNextBatchId, List<YearMonth> yearMonthsBetween) {
        // 要推月结
        List<String> yearMonthsBetweenString = ListUtil.toSingleList(yearMonthsBetween, yearMonth -> CommonUtil.getSelectedYearMonth(yearMonth.getYear(), yearMonth.getMonthValue()));

        // 获取对应月份的月结数据
        DuijieQuery duijieQuery = new DuijieQuery();
        duijieQuery.setZtDataKey(ztDataKey);
        duijieQuery.setChangedYearMonths(new LinkedHashSet<>(yearMonthsBetweenString));
        ApiMonthlySettlementServiceImpl monthlySettlementService = factory.getMonthlySettlementService();
        List<MonthlySettlementDto> monthData = monthlySettlementService.getDataByDuijieQuery(duijieQuery);

        // 设置为待推送状态
        monthlySettlementService.setDataToWaitingStatus(monthData);
        int count = 0;
        for (MonthlySettlementDto monthDatum : monthData) {
            count++;
            String thisYjBatchId = ztDataKey + "-" + System.currentTimeMillis() + "-" + monthDatum.getKJQJ() + "-yj";
            if (duijieBatchDtos.size() > 0) {
                // 把上一个循环的最后一个任务的nextBatchId设成这个月结批次id
                DuijieBatchDto lastBatch = duijieBatchDtos.get(duijieBatchDtos.size() - 1);
                if (lastBatch.getNextBatchId() == null) {
                    lastBatch.setNextBatchId(thisYjBatchId);
                }
            }

            String nextBatchId;
            if (count == monthData.size()) {
                nextBatchId = lastBatchNextBatchId;
            } else {
                nextBatchId = ztDataKey + "-" + System.currentTimeMillis() + "-" + monthData.get(count).getKJQJ() + "-yj";
            }
            DuijieBatchDto yjBatchDto = new DuijieBatchDto(null, ztDataKey, thisYjBatchId, 1, new Date());
            YearMonth yearMonthFromKJQJString = CommonUtil.getYearMonthFromKJQJString(monthDatum.getKJQJ());
            yjBatchDto.setYears(yearMonthFromKJQJString.getYear());
            yjBatchDto.setMonths(yearMonthFromKJQJString.getMonthValue());
            yjBatchDto.setNextBatchId(nextBatchId);
            duijieBatchDtos.add(yjBatchDto);
        }
    }


    /**
     * 自动按顺序分批次发送月份
     */
    @Override
    public void pushMonthDataOrderByMonthByBatch(PushMonthDataByBatchCommand pushCommand) {
        CreateBatchDataCommand command = new CreateBatchDataCommand();
        Integer years = pushCommand.getYears();
        command.setYears(years);
        Integer months = pushCommand.getMonths();
        command.setMonths(months);
        Integer endYears = pushCommand.getEndYears();
        command.setEndYears(endYears);
        Integer endMonths = pushCommand.getEndMonths();
        command.setEndMonths(endMonths);

        if (pushCommand.isPushYjOnly()) {
            // 只推月结的情况
            command.setNextBatchMap(Collections.singletonMap("yj", null));
            command.setBatchCount(1);

        } else {
            command.setNextBatchMap(SystemConstants.MONTHLY_NEXT_BATCH_MAP);
            command.setBatchCount(SystemConstants.MONTHLY_NEXT_BATCH_MAP.size());
        }

        // 获取需要对接的账套
        Set<String> ztDataKeyByAccSets = new HashSet<>();
        List<YearMonth> yearMonthsBetween = DateUtil.getYearMonthsBetween(LocalDate.of(years, months, 1), LocalDate.of(endYears, endMonths, 1));
        for (YearMonth yearMonth : yearMonthsBetween) {
            DuijieCommand duijieCommand = new DuijieCommand(yearMonth.getYear(), yearMonth.getMonthValue(), pushCommand.getAccSets());
            ztDataKeyByAccSets.addAll(dataBusiness.getNeedDuijieAccSetsByDuijieCommand(duijieCommand, factory.getDuijieApisByBatchKey("yfsj")));
        }
//        List<Object> accSets = pushCommand.getAccSets();
//        List<String> ztDataKeyByAccSets = dataManager.getZtDataKeyByAccSets(accSets);

        for (String ztDataKey : ztDataKeyByAccSets) {
            command.setZtDataKey(ztDataKey);

            String firstBatchId = duijieManager.createOrderByMonthBatchData(command);
            System.out.println(firstBatchId);

            // 启动第一批次的对接
            duijieManager.updateNextBatchDataToDuijie(firstBatchId);
        }

    }

    // 测试类 自动检测需要凭证冲洗的情况
    public void flushVoucherByTaskId(FlushVoucherCommand command) {
        // 查询所有属于这种类型的报错
        String sql = "select ZT_DATA_KEY,a.taskId as taskId,methodNo as methodNo,type as \"type\",sjjhbz as sjjhbz,writeLog as writeLog,\n" +
                "                createDate as createDate,writeDate as writeDate,batchId as batchId,acc_set as acc_set from (\n" +
                "\tselect ZT_DATA_KEY,taskId from DJ_KMCSHSJ where opType=1 and sjjhbz=2 group by ZT_DATA_KEY,taskId\n" +
                ")a, DUIJIE_ASYNC b where a.taskId=b.taskId and writeLog like '%会计科目编码%禁止删除, 该科目已被会计凭证关联使用%'\n" +
                "${taskIdSQL}\n" +
                "order by ZT_DATA_KEY";
        Map<String, Object> params;
        if (command.getTaskIds() != null && command.getTaskIds().size() > 0) {
            sql = StringUtil.replace(sql, "${taskIdSQL}", " and taskId in (:taskIds)");
            params = Collections.singletonMap("taskIds", command.getTaskIds());
        } else {
            params = Collections.emptyMap();
            sql = StringUtil.replace(sql, "${taskIdSQL}", "");
        }
        List<Map<String, Object>> maps = EntityManagerUtil.queryForMapList(entityManager, sql, params);

        // 循环每一条
        for (Map<String, Object> map : maps) {
            try {
                String ztDataKey = (String) map.get("ZT_DATA_KEY");
                String writeLog = (String) map.get("writeLog");
                // 正则匹配出所有需要凭证冲洗的凭证DATA_KEY
                List<String> voucherDataKeys = CommonUtil.getAllVoucherDataKey(writeLog);

                // 按月份进行排序
                List<String> kjqjs = CommonUtil.getKJQJFromVoucherWriteLog(writeLog)
                        .stream().distinct().sorted().collect(Collectors.toList());

                // 按凭证月份进行区分
                if (kjqjs.size() == 1) {
                    // 如果只有一个月份 就直接推 如果有多个月份 则要按批次 中间推月结？
                    pushDefaultVoucherEntryByDataKeys(ztDataKey, kjqjs.get(0), voucherDataKeys);
                } else if (kjqjs.size() > 1) {
                    // 如果有多个月份 则要按批次推送
                    Map<String, List<String>> kjqjMap = new HashMap<>();
                    for (String voucherDataKey : voucherDataKeys) {
                        String kjqj = CommonUtil.getKJQJFromVoucherDataKey(voucherDataKey);
                        kjqjMap.putIfAbsent(kjqj, new ArrayList<>());
                        kjqjMap.get(kjqj).add(voucherDataKey);
                    }

                    for (String kjqj : kjqjs) {
                        List<String> dataKeyOfKjqj = kjqjMap.get(kjqj);

                        // TODO 判断DUIJIE_DATA_KEYS是否有这些DATA_KEY 没有则要补充

                        // TODO 按批次对接那里要单独处理这种情况 推的是凭证冲洗接口
//                        pushDefaultVoucherEntryByDataKeys(factory.getVoucherService(), ztDataKey, kjqj, dataKeyOfKjqj);
                    }
                }


            } catch (Throwable throwable) {
                log.error("", throwable);
            }
        }


    }

    // 识别固定资产报错 把正确的另外再发送上去
    @Override
    public void autoProcessFixedAssetsError() {
        // 获取上次处理完的DuijieAsync表的最大id值
        Integer lastDoneFixedAssetErrorMaxId = duijieManager.getVarByKey("lastDoneFixedAssetErrorMaxId", Integer.class);
        if (lastDoneFixedAssetErrorMaxId == null) {
            lastDoneFixedAssetErrorMaxId = 0;
        }

        // 查询所有属于这种类型的报错
        String sql = "select b.id as id,TYSHXYDM,a.taskId as taskId,methodNo as methodNo,type as \"type\",sjjhbz as sjjhbz,writeLog as writeLog,\n" +
                "                createDate as createDate,writeDate as writeDate,content as content,batchId as batchId,acc_set as acc_set from (\n" +
                "\tselect TYSHXYDM,taskId from DJ_GDZC where opType=1 group by TYSHXYDM,taskId\n" +
                ")a, DUIJIE_ASYNC b where a.taskId=b.taskId and writeLog like '%资产编码%在统一社会信用代码为%的组织内重复%' " +
                "and b.sjjhbz=2 and content is not null and b.id>:lastDoneFixedAssetErrorMaxId\n" +
                "order by b.id";
        List<Map<String, Object>> maps = EntityManagerUtil.queryForMapList(entityManager, sql, Collections.singletonMap("lastDoneFixedAssetErrorMaxId", lastDoneFixedAssetErrorMaxId));

        ApiFixedAssetsServiceImpl fixedAssetsService = factory.getFixedAssetsService();

        Integer newDoneFixedAssetErrorMaxId = null;
        // 查询出所有有问题需要重对的固定资产记录
        for (Map<String, Object> map : maps) {

            try {
                // 解析日志 找出所有有问题的资产编码 排除掉
                String writeLog = (String) map.get("writeLog");
                List<String> errorAssetCodes = CommonUtil.getRepeatAssetCode(writeLog);

                String content = (String) map.get("content");
                Integer acc_set = (Integer) map.get("acc_set");
                String batchId = (String) map.get("batchId");

                JSONArray dataArrays = JSONUtil.parseArray(content);
                dataArrays.removeIf(jsonObj -> errorAssetCodes.contains(((JSONObject) jsonObj).getStr("BM")));

                // 如果排除完还有固定资产记录 就是这些是成功的 推送这些成功的
                if (dataArrays.size() > 0) {
                    // 根据固定资产DATA_KEY获取固定资产中间表的id
                    List<String> dataKeys = ListUtil.toSingleList(dataArrays, jsonObj -> ((JSONObject) jsonObj).getStr("DATA_KEY"));
                    List<Integer> ids = fixedAssetsService.getIdsByDataKeys(dataKeys);
                    fixedAssetsService.sendObjectData(dataArrays, fixedAssetsService.getDataApi(), ids, batchId, acc_set);
                    newDoneFixedAssetErrorMaxId = (Integer) map.get("id");
                }
            } catch (Throwable throwable) {
                log.error("", throwable);
            }
        }
        if (newDoneFixedAssetErrorMaxId != null) {
            duijieManager.saveVarByKey("lastDoneFixedAssetErrorMaxId", newDoneFixedAssetErrorMaxId);
            log.info("固定资产错误处理完成，本次最大id=" + newDoneFixedAssetErrorMaxId);
        }
    }

    @Override
    public String generateRandomJsonString(TestEnvDuijieCommand duijieCommand) {
        try {
            // 对content进行解码
            duijieCommand.setContent(URLDecoder.decode(duijieCommand.getContent(), Charset.defaultCharset()));
            return dataBusiness.generateRandomJsonString(duijieCommand);
        } catch (IllegalAccessException | JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void duijieToTestEnv(TestEnvDuijieCommand duijieCommand, MultipartFile file) {
        if (StringUtil.isEmpty(duijieCommand.getCreditCode())) {
            throw new RuntimeException("信用代码creditCode不能为空！");
        }
        // 对content进行解码
        duijieCommand.setContent(URLDecoder.decode(duijieCommand.getContent(), Charset.defaultCharset()));
        try {
            dataBusiness.sendToTestEnv(duijieCommand, file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    @Override
    public void buildWithProc(BuildWithProcCommand command) {
        ProcInfo procInfo = SystemConstants.PROC_KEY_MAP.get(command.getProcKey());
        String procName = procInfo.getProcName();
        List<Integer> argTypes = procInfo.getArgTypes();
        List<Object> args = command.getArgs();
        if (argTypes.size() != args.size()) {
            throw new RuntimeException("参数个数不匹配！");
        }
        StringBuffer argSql = new StringBuffer();
        Map<String, Object> params = new HashMap<>(args.size());
        int paramCount = 1;
        for (Object arg : args) {
            if (paramCount > 1) {
                argSql.append(", ");
            }
            if (arg == null) throw new RuntimeException("参数" + paramCount + "不能为空！");
            // 参数类型校验
            Integer argType = argTypes.get(paramCount - 1);
            if (argType.equals(ProcInfo.INT) && !StringUtil.isNumeric(arg.toString())) {
                throw new RuntimeException("参数" + paramCount + "应为数字类型！" + arg);
            }

            argSql.append(":a").append(paramCount);
            params.put("a" + paramCount, arg);

            paramCount ++;
        }
        if (procInfo.isHasMsg()) {
            argSql.append(", null");
        }

        // 新增一条新记录 用来记录存储过程的执行状态
        final DuijieProcLog procLog = duijieManager.createAndSaveNewDuijieProcLog(command);


        CompletableFuture.runAsync(() -> {
                    Thread.currentThread().setName("proc_" + procName + "_" + argSql);
//            sql = "declare @v_msg varchar(200); begin exec " + dataManager.getCwDBName() + procName + " " + argSql + ", @v_msg ;  end";
//            List<String> messages = EntityManagerUtil.queryForClass(entityManager, sql, params, String.class);
//            if (messages.size() > 0) {
//                result = messages.get(0);
//            }

                    String sql = "exec " + dataManager.getCwDBName() + procName + " " + argSql;
                    duijieManager.executeUpdateSql(new ExecuteUpdateSqlCommand(sql, params));

                    // 更新完成状态到proc_log
                    CheckResultDto resultDto = new CheckResultDto(true, Collections.singletonList("执行成功！"));
                    duijieManager.saveDuijieProcLog(procLog, resultDto, false);

                }, bizPool)
                .exceptionally(throwable -> {
//                    throwable.printStackTrace();
                    log.error("duijie 执行存储过程生成数据 线程执行异常：", throwable);
                    // 更新完成状态到proc_log
                    CheckResultDto resultDto = new CheckResultDto(false, Collections.singletonList("执行失败：" + throwable.getMessage()));
                    duijieManager.saveDuijieProcLog(procLog, resultDto, false);
                    return null;
                });


    }

    @Override
    public PageDTO<DuijieProcLog> getProcLogs(PageQuery duijieQuery) {
        return duijieManager.getProcLogs(duijieQuery);
    }

}
